package com.example.translator;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.TypeReference;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.chat.response.ChatResponse;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.model.output.Response;

import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.*;

public class LangChain4jTranslationService implements TranslationService {
    private String apiKey;
    private String baseUrl;
    private String model;
    private double temperature;
    private int timeout;
    private ChatModel chatModel;
    private boolean configured = false;  // 添加配置状态字段

    // 七牛云支持的推荐模型列表
    public static final List<String> QINIU_RECOMMENDED_MODELS = Arrays.asList(
        "gpt-4o-mini",          // OpenAI 经济实惠的多模态模型
        "gpt-4o",               // OpenAI 旗舰多模态模型
        "gpt-3.5-turbo",        // OpenAI 快速、廉价的模型
        "deepseek-r1",          // 深度求索 R1 模型
        "deepseek-v3",          // 深度求索 V3 模型
        "kimi-k2",              // 月之暗面 K2 模型
        "glm-4.5-air",          // 智谱 AI 轻量模型
        "gpt-oss-20b"           // OpenAI 开源模型
    );

    public LangChain4jTranslationService() {
        loadConfig();
        initializeChatModel();
    }

    private void loadConfig() {
        Properties properties = new Properties();
        try (InputStream input = getClass().getClassLoader().getResourceAsStream("config.properties")) {
            if (input == null) {
                System.err.println("无法找到config.properties文件");
                return;
            }
            properties.load(input);

            apiKey = properties.getProperty("openai.api-key");
            baseUrl = properties.getProperty("openai.base-url");
            model = properties.getProperty("openai.model");

            String tempStr = properties.getProperty("openai.temperature");
            temperature = tempStr != null ? Double.parseDouble(tempStr) : 0.7;

            String timeoutStr = properties.getProperty("openai.timeout");
            timeout = timeoutStr != null ? Integer.parseInt(timeoutStr) : 60000;

            System.out.println("=== LangChain4j配置加载成功 ===");
            System.out.println("API Key: " + (apiKey != null && !apiKey.trim().isEmpty() ? "已配置" : "未配置"));
            System.out.println("Base URL: " + baseUrl);
            System.out.println("Model: " + model);
            System.out.println("Temperature: " + temperature);
            System.out.println("Timeout: " + timeout);

            if (model != null && !model.trim().isEmpty()) {
                checkModelCompatibility();
            }

        } catch (IOException e) {
            System.err.println("加载配置文件时出错: " + e.getMessage());
        } catch (NumberFormatException e) {
            System.err.println("配置文件格式错误: " + e.getMessage());
        }
    }

    private void checkModelCompatibility() {
        if (!QINIU_RECOMMENDED_MODELS.contains(model.toLowerCase()) && 
            !QINIU_RECOMMENDED_MODELS.contains(model.toLowerCase().split("-\\d")[0])) {
            
            System.out.println("警告: 当前模型 '" + model + "' 不在七牛云推荐列表中");
            System.out.println("推荐使用以下模型:");
            for (String recommendedModel : QINIU_RECOMMENDED_MODELS) {
                System.out.println("  - " + recommendedModel);
            }
        }
    }

    private void initializeChatModel() {
        if (!isConfigured()) {
            System.err.println("配置不完整，无法初始化聊天模型");
            return;
        }

        try {
            OpenAiChatModel.OpenAiChatModelBuilder builder = OpenAiChatModel.builder()
                    .apiKey(apiKey)
                    .modelName(model)
                    .temperature(temperature)
                    .logRequests(true)
                    .logResponses(true);

            // 如果设置了基础URL，则使用自定义URL
            if (baseUrl != null && !baseUrl.trim().isEmpty()) {
                builder.baseUrl(baseUrl);
                System.out.println("使用自定义Base URL: " + baseUrl);
            }

            this.chatModel = builder.build();
            System.out.println("聊天模型初始化成功");

        } catch (Exception e) {
            System.err.println("初始化聊天模型失败: " + e.getMessage());
            e.printStackTrace();
        }
    }

    @Override
    public String translateFileName(String fileName) throws Exception {
        if (!isConfigured()) {
            throw new IllegalStateException("OpenAI API配置不正确，请检查config.properties文件");
        }

        if (chatModel == null) {
            throw new IllegalStateException("聊天模型未初始化，请检查配置");
        }

        if (fileName == null || fileName.trim().isEmpty()) {
            return fileName;
        }

        try {
            // 创建翻译提示
            String prompt = createTranslationPrompt(fileName);
            
            // 调用LangChain4j的聊天模型
            System.out.println("正在翻译文件名: " + fileName);
            System.out.println("使用提示: " + prompt);

            String response = chatModel.chat(prompt);
            
            if (response== null || response.trim().isEmpty()) {
                throw new Exception("翻译结果为空");
            }
            
            String translated = response.trim();
            System.out.println("翻译结果: " + translated);
            
            return translated;
            
        } catch (Exception e) {
            System.err.println("翻译失败: " + e.getMessage());
            e.printStackTrace();
            
            // 尝试解析LangChain4j的错误信息
            String errorMessage = e.getMessage();
            if (errorMessage != null && errorMessage.contains("400")) {
                if (errorMessage.contains("model_not_supported")) {
                    throw new Exception("模型不支持: " + model + 
                            "\n请使用七牛云推荐的模型: " + String.join(", ", QINIU_RECOMMENDED_MODELS), e);
                } else if (errorMessage.contains("invalid_api_key")) {
                    throw new Exception("API密钥无效，请检查config.properties中的api-key配置", e);
                } else {
                    throw new Exception("请求参数错误: " + errorMessage + 
                            "\n请检查模型名称和API配置是否正确", e);
                }
            }
            
            throw new Exception("翻译失败: " + e.getMessage(), e);
        }
    }

    @Override
    public Map<String, String> batchTranslateFileNames(List<String> fileNames,ProgressCallback callback) throws Exception {
        if (!isConfigured()) {
            throw new IllegalStateException("OpenAI API配置不正确，请检查config.properties文件");
        }

        if (chatModel == null) {
            throw new IllegalStateException("聊天模型未初始化，请检查配置");
        }

        if (fileNames == null || fileNames.isEmpty()) {
            return Collections.emptyMap();
        }

        // 分批处理，每批处理10个文件名
        int batchSize = 10;
        int totalFiles = fileNames.size();
        int totalBatches = (int) Math.ceil((double) totalFiles / batchSize);

        System.out.println("开始批量翻译，共 " + totalFiles + " 个文件名，分为 " + totalBatches + " 批处理");

        // 创建线程安全的Map来存储结果
        Map<String, String> allResults = new ConcurrentHashMap<>();

        // 创建线程池，线程数建议设置为CPU核心数的2倍
        int threadPoolSize = Runtime.getRuntime().availableProcessors() * 2;
        ExecutorService executorService = Executors.newFixedThreadPool(threadPoolSize);

        // 创建CountDownLatch来等待所有任务完成
        CountDownLatch latch = new CountDownLatch(totalBatches);

        // 为每个批次创建任务
        for (int batchIndex = 0; batchIndex < totalBatches; batchIndex++) {
            final int currentBatchIndex = batchIndex;
            final int startIndex = batchIndex * batchSize;
            final int endIndex = Math.min(startIndex + batchSize, totalFiles);
            final List<String> batchFileNames = fileNames.subList(startIndex, endIndex);

            executorService.submit(() -> {
                try {
                    System.out.println("正在处理第 " + (currentBatchIndex + 1) + "/" + totalBatches + " 批: " +
                            batchFileNames.size() + " 个文件名");
                    // 通知进度
                    if (callback != null) {
                        callback.onProgress(currentBatchIndex + 1, totalBatches,
                                String.format("正在处理第 %d/%d 批: %d 个文件名",
                                        currentBatchIndex + 1, totalBatches, batchFileNames.size()));
                    }
                    try {
                        // 创建批量翻译提示
                        String prompt = createBatchTranslationPrompt(batchFileNames);

                        // 调用LangChain4j的聊天模型
                        String response = chatModel.chat(prompt);

                        if (response == null || response.trim().isEmpty()) {
                            throw new Exception("第 " + (currentBatchIndex + 1) + " 批翻译结果为空");
                        }

                        String responseContent = response.trim();

                        // 解析响应内容
                        Map<String, String> batchResults = parseBatchTranslationResponse(batchFileNames, responseContent);

                        // 添加到总结果中
                        allResults.putAll(batchResults);
                        // 通知批次完成
                        if (callback != null) {
                            callback.onBatchComplete(currentBatchIndex, batchResults);
                        }

                        System.out.println("第 " + (currentBatchIndex + 1) + " 批翻译完成，成功翻译 " + batchResults.size() + " 个文件名");

                    } catch (Exception e) {
                        System.err.println("第 " + (currentBatchIndex + 1) + " 批翻译失败: " + e.getMessage());
                        if (callback != null) {
                            callback.onError(currentBatchIndex, "第 " + (currentBatchIndex + 1) + " 批翻译失败: " + e.getMessage());
                        }

                        // 尝试回退到逐个翻译当前批次
//                        System.err.println("尝试逐个翻译第 " + (currentBatchIndex + 1) + " 批文件名");
//
//                        for (String fileName : batchFileNames) {
//                            try {
//                                String translated = translateFileName(fileName);
//                                allResults.put(fileName, translated);
//                                System.out.println("单个翻译成功: " + fileName);
//                            } catch (Exception fallbackEx) {
//                                System.err.println("单个翻译失败: " + fileName + " - " + fallbackEx.getMessage());
//                                allResults.put(fileName, fileName); // 保持原文件名
//                            }
//                        }
                    }
                } finally {
                    latch.countDown();
                }
            });
        }

        // 等待所有任务完成
        latch.await();

        // 关闭线程池
        executorService.shutdown();

        System.out.println("批量翻译全部完成，总共成功翻译 " + allResults.size() + " 个文件名");
        return allResults;
    }

    @Override
    public void updateConfig(Properties config) throws Exception {
        if (config == null) {
            throw new IllegalArgumentException("配置不能为空");
        }

        String apiKey = config.getProperty("openai.api-key");
        if (apiKey == null || apiKey.trim().isEmpty()) {
            throw new IllegalArgumentException("API Key不能为空");
        }

        String baseUrl = config.getProperty("openai.base-url","https://api.qnaigc.com/v1");
        String model = config.getProperty("openai.model", "gpt-3.5-turbo");
        String temperature = config.getProperty("openai.temperature", "0.7");
        String maxTokens = config.getProperty("openai.max.tokens", "2000");

        // 重新创建聊天模型
        this.chatModel = OpenAiChatModel.builder()
                .baseUrl(baseUrl)
                .apiKey(apiKey)
                .modelName(model)
                .temperature(Double.parseDouble(temperature))
                .maxTokens(Integer.parseInt(maxTokens))
                .build();
        System.out.println("=== LangChain4j自定义配置加载成功 ===");
        System.out.println("API Key: " + (apiKey != null && !apiKey.trim().isEmpty() ? "已配置" : "未配置"));
        System.out.println("Base URL: " + baseUrl);
        System.out.println("Model: " + model);

        // 更新配置状态
        this.configured = true;
    }


    private String createTranslationPrompt(String fileName) {
        return "请将以下英文文件名翻译成中文，保持专业术语的准确性，对于缩写请给出完整含义：\n" +
                "文件名：" + fileName + "\n" +
                "翻译要求：\n" +
                "1. 保持文件名的简洁性和可读性\n" +
                "2. 专业术语和技术缩写需要需要准确翻译\n" +
                "3. 保持文件名的语义完整\n" +
                "4. 只返回翻译后的文件名，不要添加额外解释\n" +
                "5. 如果无法翻译或不需要翻译，请返回原文件名";
    }

    /**
     * 创建批量翻译提示
     */
    private String createBatchTranslationPrompt(List<String> fileNames) {
        StringBuilder promptBuilder = new StringBuilder();

        promptBuilder.append("请将以下英文文件名列表翻译成中文，保持专业术语的准确性，对于缩写请给出完整含义：\n");
        promptBuilder.append("翻译要求：\n");
        promptBuilder.append("1. 保持文件名的简洁性和可读性\n");
        promptBuilder.append("2. 专业术语和技术缩写需要准确翻译\n");
        promptBuilder.append("3. 保持文件名的语义完整\n");
        promptBuilder.append("4. 请按照以下JSON格式返回翻译结果：\n");
        promptBuilder.append("{\n");
        promptBuilder.append("  \"translations\": {\n");
        promptBuilder.append("    \"原文件名1\": \"翻译后的文件名1\",\n");
        promptBuilder.append("    \"原文件名2\": \"翻译后的文件名2\",\n");
        promptBuilder.append("    ...\n");
        promptBuilder.append("  }\n");
        promptBuilder.append("}\n");
        promptBuilder.append("5. 不要添加任何额外解释或说明文字\n");
        promptBuilder.append("6. 如果无法翻译或不需要需要翻译的文件名，请保持原样\n");
        promptBuilder.append("\n文件名列表：\n");

        for (int i = 0; i < fileNames.size(); i++) {
            promptBuilder.append((i + 1)).append(". ").append(fileNames.get(i)).append("\n");
        }

        return promptBuilder.toString();
    }

    /**
     * 解析批量翻译响应
     */
    private Map<String, String> parseBatchTranslationResponse(List<String> originalFileNames, String responseContent) {
        Map<String, String> results = new HashMap<>();

        try {
            // 尝试解析JSON格式
            if (responseContent.startsWith("{") && responseContent.endsWith("}")) {
                // 尝试使用FastJSON解析JSON
                try {
                    Map<String, Object> jsonResponse = JSON.parseObject(responseContent, new TypeReference<Map<String, Object>>() {});

                    if (jsonResponse.containsKey("translations")) {
                        Object translationsObj = jsonResponse.get("translations");
                        if (translationsObj instanceof Map) {
                            Map<?, ?> translationsMap = (Map<?, ?>) translationsObj;

                            for (Map.Entry<?, ?> entry : translationsMap.entrySet()) {
                                String original = String.valueOf(entry.getKey());
                                String translated = String.valueOf(entry.getValue());
                                results.put(original, translated);
                            }

                            // 检查是否有遗漏的文件名
                            for (String fileName : originalFileNames) {
                                if (!results.containsKey(fileName)) {
                                    results.put(fileName, fileName); // 未翻译的文件名保持原样
                                }
                            }

                            return results;
                        }
                    }
                } catch (Exception e) {
                    System.err.println("JSON解析失败，尝试其他格式格式解析: " + e.getMessage());
                }
            }

            // 如果JSON解析失败，尝试解析简单格式
            String[] lines = responseContent.split("\\n");

            for (String line : lines) {
                line = line.trim();
                if (line.isEmpty()) continue;

                // 尝试解析 "原文件名 -> 翻译后文件名" 格式
                if (line.contains("->")) {
                    String[] parts = line.split("->", 2);
                    if (parts.length == 2) {
                        String original = parts[0].trim();
                        String translated = parts[1].trim();

                        // 移除可能的引号
                        original = original.replaceAll("^[\"']|[\"']$", "");
                        translated = translated.replaceAll("^[\"']|[\"']$", "");

                        results.put(original, translated);
                    }
                }
                // 尝试解析 "数字. 原文件名: 翻译后文件名" 格式
                else if (line.matches("^\\d+\\. .+:.+$")) {
                    String[] parts = line.split(":", 2);
                    if (parts.length == 2) {
                        String originalPart = parts[0].trim().replaceAll("^\\d+\\. ", "");
                        String translated = parts[1].trim();

                        results.put(originalPart, translated);
                    }
                }
            }

            // 检查是否有遗漏的文件名
            for (String fileName : originalFileNames) {
                if (!results.containsKey(fileName)) {
                    results.put(fileName, fileName); // 未翻译的文件名保持原样
                }
            }

        } catch (Exception e) {
            System.err.println("解析批量翻译响应失败: " + e.getMessage());

            // 如果解析失败，返回原文件名
            for (String fileName : originalFileNames) {
                results.put(fileName, fileName);
            }
        }

        return results;
    }
    @Override
    public boolean isConfigured() {
        boolean configured = apiKey != null && !apiKey.trim().isEmpty() &&
                           model != null && !model.trim().isEmpty();

        if (!configured) {
            System.err.println("=== 配置不完整 ===");
            if (apiKey == null || apiKey.trim().isEmpty()) {
                System.err.println("缺少API Key");
            }
            if (model == null || model.trim().isEmpty()) {
                System.err.println("缺少Model");
            }
        }

        return configured;
        //return configured && chatModel != null;
    }

    /**
     * 获取七牛云推荐的模型列表
     * @return 推荐模型列表
     */
    public static List<String> getRecommendedModels() {
        return new ArrayList<>(QINIU_RECOMMENDED_MODELS);
    }

    /**
     * 测试模型连接
     * @return 连接成功返回true，否则返回false
     */
    public boolean testConnection() {
        if (!isConfigured() || chatModel == null) {
            return false;
        }

        try {
            System.out.println("正在测试模型连接...");
            String response = chatModel.chat("测试连接");
            System.out.println("连接测试成功，响应: " + response);
            return true;
        } catch (Exception e) {
            System.err.println("连接测试失败: " + e.getMessage());
            return false;
        }
    }
}
